package com.tinysand.advert.mysql.dto;

import com.tinysand.advert.mysql.constant.OperationType;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

/**
 * @author TINY
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ParseTemplate {
    private String database;
    /* K: tableName, V:tableTemplate*/
    private Map<String, TableTemplate> tableTemplateMap =
            new HashMap<>();

    public static ParseTemplate parseTemplate(Template template) {
        ParseTemplate parseTemplate = new ParseTemplate();
        parseTemplate.setDatabase(template.getDatabase());

        for (JsonTable table : template.getTables()) {
            String name = table.getTableName();
            Integer level = table.getLevel();

            TableTemplate tableTemplate = new TableTemplate();
            tableTemplate.setTableName(name);
            tableTemplate.setLevel(level.toString());
            parseTemplate.tableTemplateMap.put(name, tableTemplate);

            // 遍历操作类型对应的列
            Map<OperationType, List<String>> opTypeFieldMap =
                    tableTemplate.getOpTypeFieldMap();

            for (JsonTable.Column column : table.getInsert()) {
                getOrCreate(
                        OperationType.ADD, opTypeFieldMap,
                        ArrayList::new
                ).add(column.getColumn());
            }

            for (JsonTable.Column column : table.getUpdate()) {
                getOrCreate(
                        OperationType.UPDATE, opTypeFieldMap,
                        ArrayList::new
                ).add(column.getColumn());
            }

            for (JsonTable.Column column : table.getDelete()) {
                getOrCreate(
                        OperationType.DELETE, opTypeFieldMap,
                        ArrayList::new
                ).add(column.getColumn());
            }
        }
        return parseTemplate;
    }

    private static <T, R> R getOrCreate(T key, Map<T, R> map,
                                        Supplier<R> factory) {
        return map.computeIfAbsent(key, k -> factory.get());
    }
}
